﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Threading.Tasks;
using FDSimpleModelGenerator.Entities;
using FDSimpleModelGenerator.IRepositories;
using FDSimpleModelGenerator.IServices;
using Microsoft.Data.Sqlite;

namespace FDSimpleModelGenerator.Repositories
{
    /// <summary>
    /// 基础访问
    /// </summary>
    public class BasicRepository<T> : IBasicRepository<T> where T : IEntity, new()
    {
        protected readonly DbConnectionInfo _dbConnectionInfo;
        protected readonly IDbAccessor _dbAccessor;
        protected readonly IGenerateDbSql _generateDbSql;

        public BasicRepository(DbConnectionInfo dbConnection, IDbAccessor dbAccessor, IGenerateDbSql generateDbSql)
        {
            _dbAccessor = dbAccessor;
            _dbConnectionInfo = dbConnection;
            dbAccessor.Init(() => new SqliteConnection(_dbConnectionInfo.ConnectionString));
            _generateDbSql = generateDbSql;
        }

        public bool Add(T model)
        {
            var sql = _generateDbSql.GetInsertString<T>();
            // 目前为sqlite，所以写法为 select last_insert_rowid()
            sql += ";select last_insert_rowid();";
            var id = _dbAccessor.ExecuteScalar<int>(sql, model);
            model.Id = id;
            return id > 0;
        }

        public bool Update(T model)
        {
            var sql = _generateDbSql.GetUpdateString<T>("Id=@Id");
            return _dbAccessor.ExecuteNoneQuery(sql, model) > 0;
        }

        public bool AddOrUpdate(T model)
        {
            if (model.Id == 0)
            {
                return Add(model);
            }
            return Update(model);
        }

        public bool Delete(int id)
        {
            var sql = _generateDbSql.GetDeleteString<T>("Id=@Id");
            return _dbAccessor.ExecuteNoneQuery(sql, new { Id = id }) > 0;
        }

        public T Get(int id)
        {
            var sql = _generateDbSql.GetQueryString<T>("Id=@Id");
            return _dbAccessor.Get<T>(sql, new { Id = id });
        }

        public IList<T> GetList()
        {
            var sql = _generateDbSql.GetQueryString<T>("");
            return _dbAccessor.GetList<T>(sql);
        }

        public TModel ExecutScalar<TModel>(string sql, object param = null)
        {
            return _dbAccessor.ExecuteScalar<TModel>(sql, param);
        }

        public TModel Query<TModel>(string sql, object param = null)
        {
            return _dbAccessor.Get<TModel>(sql, param);
        }

        public int ExecuteNoneQuery(string sql, object param = null)
        {
            return _dbAccessor.ExecuteNoneQuery(sql, param);
        }

        #region  异步操作
        public async Task<bool> AddAsync(T model)
        {
            var sql = _generateDbSql.GetInsertString<T>();
            // 目前为sqlite，所以写法为 select last_insert_rowid()
            sql += ";select last_insert_rowid();";
            var id = await _dbAccessor.ExecuteScalarAsync<int>(sql, model);
            model.Id = id;
            return id > 0;
        }

        public async Task<bool> UpdateAsync(T model)
        {
            var sql = _generateDbSql.GetUpdateString<T>("Id=@Id");
            return await _dbAccessor.ExecuteNoneQueryAsync(sql, model) > 0;
        }

        public async Task<bool> AddOrUpdateAsync(T model)
        {
            if (model.Id == 0)
            {
                return await AddAsync(model);
            }
            return await UpdateAsync(model);
        }

        public async Task<bool> DeleteAsync(int id)
        {
            var sql = _generateDbSql.GetDeleteString<T>("Id=@Id");
            return await _dbAccessor.ExecuteNoneQueryAsync(sql, new { Id = id }) > 0;
        }

        public async Task<T> GetAsync(int id)
        {
            var sql = _generateDbSql.GetQueryString<T>("Id=@Id");
            return await _dbAccessor.GetAsync<T>(sql, new { Id = id });
        }

        public async Task<IList<T>> GetListAsync()
        {
            var sql = _generateDbSql.GetQueryString<T>("");
            return await _dbAccessor.GetListAsync<T>(sql);
        }

        public async Task<int> ExecuteNoneQueryAsync(string sql, object param = null)
        {
            return await _dbAccessor.ExecuteNoneQueryAsync(sql, param);
        }

        public async Task<TModel> ExecutScalarAsync<TModel>(string sql, object param = null)
        {
            return await _dbAccessor.ExecuteScalarAsync<TModel>(sql, param);
        }

        public async Task<TModel> QueryAsync<TModel>(string sql, object param = null)
        {
            return await _dbAccessor.GetAsync<TModel>(sql, param);
        }

        public async Task<IDbConnection> BeginTransaction()
        {
            return await _dbAccessor.BeginTransaction();
        }

        public async Task<bool> CommitTransaction()
        {
            return await _dbAccessor.CommitTransaction();
        }

        public async Task<bool> RollbackTransaction()
        {
            return await _dbAccessor.RollbackTransaction();
        }

        #endregion
    }
}
